package Model.Draw.Entities;

import Model.Draw.Entities.Impl.StateJoint;
import Model.Draw.IMachineStateDraw;
import Model.Draw.IStateDraw;
import Model.Draw.Point;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

public class TransitionDraw implements IMachineStateDraw {

    private IStateDraw source;
    private IStateDraw target;
    private Color color;
    private boolean selected;
    private String eventName;
    private Rectangle2D eventRectangle;

    public TransitionDraw(IStateDraw source, IStateDraw target) {
        this.source = source;
        this.target = target;
        selected = false;
    }

    @Override
    public void draw(Graphics g) {
        StateJoint jointSource = source.findNearstJointOf(target);
        StateJoint jointTarget = target.findNearstJointOf(source);
        drawArrow(g, jointSource.getLinkPoint(), jointTarget.getLinkPoint());
        drawString(g, jointSource, jointTarget);
    }

    private void drawArrow(Graphics g, Point p1, Point p2) {
        double dia = 25.0;
        double barb = 15.0;
        double phi = Math.toRadians(20);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        double dy = p2.getY().getCoordinate() - p1.getY().getCoordinate();
        double dx = p2.getX().getCoordinate() - p1.getX().getCoordinate();
        double theta = Math.atan2(dy, dx);
        double x1 = p1.getX().getCoordinate() + (dia / 2) * Math.cos(theta);
        double y1 = p1.getY().getCoordinate() + (dia / 2) * Math.sin(theta);
        theta += Math.PI;
        double x2 = p2.getX().getCoordinate() + (dia / 2) * Math.cos(theta);
        double y2 = p2.getY().getCoordinate() + (dia / 2) * Math.sin(theta);
        g2.setPaint(Color.green.darker());
        g2.draw(new Line2D.Double(x1, y1, x2, y2));
        double xa = x2 + barb * Math.cos(theta + phi);
        double ya = y2 + barb * Math.sin(theta + phi);
        g2.draw(new Line2D.Double(x2, y2, xa, ya));
        double xb = x2 + barb * Math.cos(theta - phi);
        double yb = y2 + barb * Math.sin(theta - phi);
        g2.draw(new Line2D.Double(x2, y2, xb, yb));
    }

    private void drawString(Graphics g, Point p, Point p2) {
        double x, y;

        if (p.getX().getCoordinate() < p2.getX().getCoordinate()) {
            if (p.getY().getCoordinate() < p2.getY().getCoordinate()) {
                x = p.getX().getCoordinate() + 20;
                y = p.getY().getCoordinate() + 20;
            } else {
                x = p.getX().getCoordinate() + 20;
                y = p2.getY().getCoordinate() - 20;
            }
        } else {
            if (p.getY().getCoordinate() > p2.getY().getCoordinate()) {
                x = p2.getX().getCoordinate() + 25;
                y = p.getY().getCoordinate() + 20;
            } else {
                x = p2.getX().getCoordinate() + 20;
                y = p2.getY().getCoordinate() - 20;
            }
        }

        if (eventName == null || eventName.isEmpty()) {
            eventName = "efetuar";
        }
        Font mFont = g.getFont();
        eventRectangle = mFont.getStringBounds(eventName, ((Graphics2D) g).getFontRenderContext());
        eventRectangle.setRect((int) x, (int) (y - eventRectangle.getHeight() * 0.8), (int) (eventRectangle.getWidth()), (int) eventRectangle.getHeight());
        g.setColor(getColor());
        g.drawString(eventName, (int) x, (int) y);
    }

    public Color getColor() {
        return selected ? Color.RED : Color.BLACK;
    }

    @Override
    public boolean contains(int x, int y) {
        return eventRectangle != null ? eventRectangle.contains(x, y) : false;
    }

    @Override
    public void select() {
        selected = true;
    }

    @Override
    public void unselect() {
        selected = false;
    }

    @Override
    public void move(int newX, int newY) {
        //TODO Michele: move
    }

    @Override
    public void rename(String newName) {
        eventName = newName;
    }

    @Override
    public String getDescription() {
        return eventName;
    }
}
